<?php

class StmtMySQLi extends mysqli_stmt implements DatabaseStatement
{
    protected $_query = '';
    protected $_types = NULL;
    
    protected $_boundParams;
    protected $_boundResult;
    
    public function __construct($link, $query, $types)
    {
        parent::__construct($link, $query);
        $this->_query = $query;
        if ($this->parameterCount() != strlen($types)) {
            throw new StatementException('construct: bad types-placeholder count');
        }
        $this->_types = $types;
    }
    
    public function affectedRows()
    {
        return $this->affected_rows ? $this->affected_rows : false;
    }
    
    public function lastInsertID()
    {
        return $this->insert_id ? $this->insert_id : false;
    }
    
    public function execute(array $values = NULL, $getall = false)
    {
        if ($this->parameterCount() != count($values)) {
            throw new StatementException('Invalid valuecount');
        }
        if (!empty($values)) {
            if (empty($this->_boundParams)) {
                $this->_boundParams = array();
                $args = array($this->_types);
                for ($i=0;$i<$this->parameterCount();++$i) {
                    $this->_boundParams[$i] = &${'p'.$i};
                    $args[] = &$this->_boundParams[$i];
                }
                call_user_func_array(array($this,'bind_param'), $args);
            }
            $i = 0;
            foreach ($values as $v) {
                $this->_boundParams[$i] = $v;
                ++$i;
            }
        }
        if (!parent::execute()) {
            throw new StatementException('Failed to execute! SQLState:'.$this->sqlstate);
        }
        if (!empty($this->error)) {
            throw new SQLException($this->error,$this->errno);
        }
        if ($meta = $this->result_metadata()) {
            if (isset($this->_boundResult)) {
                $this->_boundResult = $row = array();
                while ($field = $meta->fetch_field()) {
                    $this->_boundResult[$field->name] = &$row[$field->name];
                }
                call_user_func_array(array($this,'bind_result'), $this->_boundResult);
            }
            return $this->fetchArray();
        }
        if ($this->lastInsertID()) {
            return $this->lastInsertID();
        }
        if ($this->affectedRows()) {
            return $this->affectedRows();
        }
        return ('Unknown statementtype');
    }
    
    public function fetchArray()
    {
        if (!isset($this->_boundResult)) {
            throw new StatementException('No result available yet');
        }
        if (!$this->fetch()) {
            return NULL;
        }
        $this->store_result();
        $ret = array();
        foreach ($this->_boundResult as $field => $value) {
            $ret[$field] = $value;
        }
        return $ret;
    }
    
    /**
     * Fetch one result (array)
     *
     * @param MYSQLI_RESULTMODE_TYPE $resultmode
     * @return array $result
     */
    public function getOne($resultmode = MYSQLI_ASSOC)
    {
        $this->execute();
        $result = $row = $result_both = array();
        $meta = $this->result_metadata();
        while ($field = $meta->fetch_field()) {
            switch ($resultmode) {
                case MYSQLI_ASSOC:
                    $result[$field->name] = &$row[$field->name];
                    break;
                    
                case MYSQLI_NUM:
                    $result[] = &$row[$field->name];
                    break;
                    
                case MYSQLI_BOTH:
                    $result[$field->name] = &$row[$field->name];
                    $result_both[] = &$row[$field->name];
            }
        }
        call_user_func_array(array($this,'bind_result'),$result);
        $this->fetch();
        $this->free_result();
        return $result+$result_both;
    }
    public function bindParameters($types, &$params)
    {
        /*
        $params = array();
        for ($i=0;$i<$this->parameterCount();++$i) {
            $params[$i] = &${'p'.$i};
            $args[] &= $params[$i];
        }
        return call_user_func_array(array($this,'bind_param'),&$args);
        */
        $params = array();
        $args = array($types);
        for ($i=0;$i<$this->parameterCount();++$i) {
            $params[$i] = &${'p'.$i};
            $args[] = &$params[$i];
        }
        #array_unshift($params,$types);
        return call_user_func_array(array($this,'bind_param'), $args);
    }
    public function parameterCount()
    {
        return $this->param_count;
    }
}
